using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Samples.SsbTransportChannel;
using System.ServiceModel;
using SsbTransportTestSuite.Proxies.OneWay;
using System.Threading;
using System.Transactions;
using System.Runtime.Serialization;
using System.ServiceModel.Channels;

namespace SsbTransportTestSuite.Clients
{

    class TestPersistentClient
    {

        internal static ManualResetEvent orderCompleted;
        internal void RunClient(Binding binding)
        {
            TestPersistentClient.orderCompleted = new ManualResetEvent(false);
            TestPersistentClient.orderCompleted.Reset();
            ServiceHost host = new ServiceHost(typeof(OrderNotificationProcessor));
            host.AddServiceEndpoint(typeof(IOrderNotification), binding, TestUtils.ClientEndpointAddress);
            host.Open();

            OrderProcessingClient client = new OrderProcessingClient(binding, new EndpointAddress(TestUtils.ServiceEndpointAddress));
            client.Open();
            SsbConversationSender sender = client.InnerChannel.GetProperty<SsbConversationSender>();
            Guid cid = sender.BeginNewConversation();
            Order order = GetOrder();
            using (TransactionScope scope = new TransactionScope())
            {
                client.BeginOrder(order);
                DBUtils.AddClientOrder(sender.GetConnection(), cid, order.OrderId);
                scope.Complete();
            }
           
            foreach (OrderItem item in GetOrderItems())
            {
                Thread.Sleep(200); //let the service channel close so the service instance will serialize
                client.AddOrderItem(item);
            }
            client.EndOrder();
            client.Close();
            //wait for the order to be completed
            TestPersistentClient.orderCompleted.WaitOne(TestUtils.TestTimeout, false);
            host.Close();
        }
        Order GetOrder()
        {
            Order order = new Order();
            order.OrderId = Guid.NewGuid();
            order.CustomerName = "ACME International Inc";
            return order;
        }
        OrderItem[] GetOrderItems()
        {
            OrderItem[] items = new OrderItem[2];
            items[0] = new OrderItem();
            items[0].ItemDescription = "Widget #1";
            items[0].Quantity = 123;
            items[0].Amount = 3902.67M;
            items[1] = new OrderItem();
            items[1].ItemDescription = "Widget #2";
            items[1].Quantity = 7;
            items[1].Amount = 13209.99M;
            return items;
        }

        public class OrderNotificationProcessor : IOrderNotification
        {
            #region IOrderNotification Members

            public void ConfirmOrder()
            {
                Console.WriteLine("Confirm order called");
                SsbConversationGroupReceiver receiver = OperationContext.Current.Channel.GetProperty<SsbConversationGroupReceiver>();
                Guid cid = ((SsbConversationContext)OperationContext.Current.IncomingMessageProperties[SsbConstants.SsbConversationMessageProperty]).ConversationHandle;
                using (TransactionScope scope = new TransactionScope(receiver.GetTransaction()))
                {
                    DBUtils.UpdateClientOrderStatus(receiver.GetConnection(), cid, OrderStatus.Confirmed);
                    scope.Complete();
                }
            }

            public void UpdateOrderStatus(OrderStatus status)
            {
                Console.WriteLine("UpdateOrderStatus called");
                SsbConversationGroupReceiver receiver = OperationContext.Current.Channel.GetProperty<SsbConversationGroupReceiver>();
                Guid cid = ((SsbConversationContext)OperationContext.Current.IncomingMessageProperties[SsbConstants.SsbConversationMessageProperty]).ConversationHandle;
                using (TransactionScope scope = new TransactionScope(receiver.GetTransaction()))
                {
                    DBUtils.UpdateClientOrderStatus(receiver.GetConnection(), cid, status);
                    scope.Complete();
                }
                if (status == OrderStatus.Shipped)
                {
                    receiver.EndConversation();
                    TestPersistentClient.orderCompleted.Set();
                }

            }

            #endregion

        }
    }
}
